package com.common.sdk.net.connect.http;

import android.content.Context;

import com.android.sohu.sdk.common.toolbox.LogUtils;
import com.android.sohu.sdk.common.toolbox.StringUtils;
import com.common.sdk.net.connect.http.center.ErrorType;
import com.common.sdk.net.connect.http.center.tools.CacheUtils;
import com.common.sdk.net.connect.http.model.AppBaseInfo;
import com.common.sdk.net.connect.http.model.HttpError;
import com.common.sdk.net.connect.http.model.OkHttpSession;
import com.common.sdk.net.connect.http.model.RequestTag;
import com.common.sdk.net.connect.http.util.OkhttpCacheUtil;
import com.common.sdk.net.connect.http.util.SohuRequestBuilder;
import com.common.sdk.net.connect.interfaces.IResponseListener;
import com.common.sdk.net.connect.interfaces.IResultParser;
import com.common.sdk.net.connect.interfaces.impl.NoThingToDoParser;

import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import okhttp3.CacheControl;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;

/**
 * Created by chengjiangsang116630 on 2018/1/17.
 */

public class OkhttpManager {

    private static AppBaseInfo baseInfo;
    private String requestTag;

    private static final String TAG = "OkhttpManager";

    private static OKHttpRequestPool okHttpRequestPool;

    // 备用域名
    private static String backupDomain;
    // 正式域名-测试域名键值对，用于测试地址替换
    private static Map<String, Map<String, String>> domainMap = new ConcurrentHashMap<>();;

    public static String getBackupDomain() {
        return backupDomain;
    }

    public static void setBackupDomain(String backupDomain) {
        OkhttpManager.backupDomain = backupDomain;
    }

    public OkhttpManager() {
        requestTag = this.toString() + System.currentTimeMillis();
    }

    public static AppBaseInfo getBaseInfo() {
        return baseInfo;
    }

    public static void setBaseInfo(AppBaseInfo baseInfo) {
        OkhttpManager.baseInfo = baseInfo;
    }

    /**
     * 添加正式地址-测试地址的键值对，用于正式地址与测试地址的切换
     * 只可做能用地址开关切换，对于只想替换一个请求的需要自己在外部替换
     * @param formal 正式地址
     * @param test 测试地址
     */
    public static void putDomainKeyValue(String key, String formal, String test) {
        if (StringUtils.isBlank(key) || StringUtils.isBlank(formal) || StringUtils.isBlank(test)) {
            return;
        }
        Map<String, String> map = new HashMap<>();
        map.put(formal, test);
        domainMap.put(formal, map);
    }

    public static void removeDomainKeyValue(String key) {
        if (StringUtils.isBlank(key)) {
            return;
        }
        domainMap.remove(key);
    }

    public static void putDomains(String key, Map<String, String> subDomainMap) {
        if (StringUtils.isNotBlank(key) && subDomainMap != null && subDomainMap.size() > 0) {
            domainMap.put(key, subDomainMap);
        }
    }

    public static void removeDomains(Set<String> keys) {
        if (keys != null && keys.size() > 0) {
            domainMap.keySet().removeAll(keys);
        }
    }

    public static Map<String, Map<String, String>> getDomainMap() {
        return domainMap;
    }

    /**
     * 需要替换为备用域名的域名列表
     */
    private static List<String> replacableDomains = new ArrayList<>();

    public static void addReplacableDomain(String domain) {
        replacableDomains.add(domain);
    }

    public static void addReplacableDomain(List<String> domains) {
        replacableDomains.addAll(domains);
    }

    public static List<String> getReplacableDomains() {
        return replacableDomains;
    }

    public static boolean staticDomainReplace() {
        return OKHttpRequestPool.staticDomainReplace();
    }

    /**
     * 使用备用域名时发送统计点到此地址
     */
    private static final String BACKUP_DOMAIN_STATISTIC_URL = "http://d.dcenter.sohuno.com/datarelay/data/uploadFailureData?time=%d&domain=%s";

    public static void init(Context context) {
        init(context, null);
    }

    public static void init(Context context, SohuNetConfig config) {
        CacheUtils.initiateDirectory(context);
        ImageRequestManager.initialize(context);
        okHttpRequestPool = new OKHttpRequestPool(context, config);
    }

    // 只初始化数据网络部分，不包含图片库
    public static void initOnlyDataRequest(Context context, SohuNetConfig config) {
        CacheUtils.initiateDirectory(context);
        okHttpRequestPool = new OKHttpRequestPool(context, config);
    }

    public static void setBaseParams(Map<String, Object> baseParams) {
        SohuRequestBuilder.init(baseParams);
    }

    public static void setBaseParam(String key, String value) {
        SohuRequestBuilder.setBaseParam(key, value);
    }

    private static OKHttpRequestPool getOkHttpRequestPool() {
        if (okHttpRequestPool == null) {
            okHttpRequestPool = new OKHttpRequestPool();
            LogUtils.e(TAG, "U INVOKE NET REQUEST BEFORE init METHOD ! THIS MAY PRODUCE UNEXPECTED RESULT");
        }
        return okHttpRequestPool;
    }
    /**
     * 同步执行一个请求, 使用此方法需要自己关闭response及body()
     * @param request
     * @return 原始response
     */
    public Response rawExecute(Request request) {
        // checkUrl
        if (!checkUrl(request)) {
            return null;
        }
        return getOkHttpRequestPool().execute(request);
    }

    public String execute(Request request) {
        return execute(request, null);
    }
    /**
     * 同步执行一个请求
     * @param request
     */
    public String execute(Request request, CacheControl cacheControl) {
        // checkUrl
        if (!checkUrl(request)) {
            return null;
        }
        if (cacheControl != null) {
            request = request.newBuilder().cacheControl(cacheControl).build();
        }

        // 返回response字符串
        Response response = getOkHttpRequestPool().execute(request);
        if (response != null) {
            ResponseBody body = response.body();
            if (body != null) {
                try {
                    return body.string();
                } catch (Exception e) {
                    LogUtils.e(TAG, e);
                }
            }
        }
        return null;
    }

    /**
     * 外部调用应该不多，甚至没有
     * @param request
     * @param callback
     * @param parser
     * @param cache
     * @param tag
     */
    public void enqueue(Request request, IResponseListener callback, IResultParser parser, CacheControl cache, String tag) {
        // checkUrl
        if (!checkUrl(request)) {
            if (callback != null) {
                HttpError error = new HttpError(ErrorType.ERROR_CLIENT_PARAM_INVALID, "request or url is invalid");
                callback.onFailure(error, null);
            }
            return;
        }

        RequestTag requestTag;
        if (tag != null) {
            // 优先使用传进来的tag
            requestTag = new RequestTag(callback, tag);
        } else {
            // 其次使用request里带的tag,最后使用本对象的tag
            requestTag = getRequestTag(request, callback);
        }
        if (cache != null) {
            request = request.newBuilder().tag(requestTag).cacheControl(cache).build();
        } else {
            request = request.newBuilder().tag(requestTag).build();
        }
        if (parser == null) {
            parser = new NoThingToDoParser();
        }
        getOkHttpRequestPool().enqueue(request, parser);
    }

    public void enqueue(Request request, IResponseListener callback, IResultParser parser, CacheControl cache) {
        enqueue(request, callback, parser, cache, null);
    }

    /**
     * 把请求加入队列， 异步执行
     * @param request
     * @param callback
     * @param parser
     */
    public void enqueue(Request request, IResponseListener callback, IResultParser parser) {
        enqueue(request, callback, parser, null);
    }

    public void enqueue(Request request, IResponseListener callback) {
        enqueue(request, callback, null);
    }

    private RequestTag getRequestTag(Request request, IResponseListener callback) {
        RequestTag tag = null;
        // 如果原request的tag不为空，则使用原tag作为新tag,否则使用本对象的tag
        if (request.tag() != null) {
            Object originTag = request.tag();
            if (originTag.equals(request)) {
                tag = new RequestTag(callback, requestTag);
            } else {
                tag = new RequestTag(callback, originTag.toString());
            }
        } else {
            tag = new RequestTag(callback, requestTag);
        }
        return tag;
    }

    /**
     * 取消所有tag = tag的请求
     * @param tag
     */
    public void cancel(String tag) {
        getOkHttpRequestPool().cancel(tag);
    }

    public void cancel() {
        cancel(requestTag);
    }

    /**
     * 取消所有请求， 在应用退出时调用
     */
    public static void cancelAll() {
        getOkHttpRequestPool().cancelAll();
    }

    /** 工具方法 */
    private boolean checkUrl(Request request) {
        if (request == null || request.url() == null || request.url().uri() == null) {
            return false;
        }

        URI uri = request.url().uri();
        String host = uri.getHost();
        if (StringUtils.isBlank(host)) {
            return false;
        }

        return true;

    }
}
